home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr47 / dos6mm.zip / CMOSSAVE.ASM < prev    next >
Assembly Source File  |  1993-03-31  |  21KB  |  462 lines

  1. ;****************************************************************************
  2. ; CMOSSAVE saves the contents of CMOS RAM to a file. Its syntax is:
  3. ;
  4. ;       CMOSSAVE [d:][path]filename [/nnn]
  5. ;
  6. ; where "filename" is the name of the file to which CMOS data will be
  7. ; saved, and "nnn" specifies the number of bytes to save. Valid values
  8. ; for "nnn" are 64 to 256. If the /nnn switch is omitted, CMOSSAVE
  9. ; determines how many bytes of CMOS your PC contains and saves them all.
  10. ; Use CMOSRSTR to restore CMOS RAM data.
  11. ;****************************************************************************
  12.  
  13. CMOS_ADDR       equ     70h                     ;CMOS address port
  14. CMOS_DATA       equ     71h                     ;CMOS data port
  15.  
  16. code            segment
  17.                 assume  cs:code,ds:code
  18.                 org     100h
  19. begin:          jmp     main
  20.  
  21. copyright       db      "CMOSSAVE 2.0 Copyright (c) 1993 Jeff Prosise",13,10
  22.                 db      "From: PC Magazine DOS 6 Memory Management "
  23.                 db      "with Utilities",13,10,13,10,"$"
  24.  
  25. helpmsg         db      "Saves the configuration data stored in CMOS RAM to "
  26.                 db      "a file.",13,10,13,10
  27.                 db      "CMOSSAVE [d:][path]filename [/nnn]",13,10,13,10
  28.                 db      "  filename  Name of the file to which configuration "
  29.                 db      "data will be saved.",13,10
  30.                 db      "  /nnn      Number of bytes of CMOS RAM to save."
  31.                 db      13,10,13,10
  32.                 db      "Use CMOSRSTR to restore CMOS configuration data."
  33. crlf            db      13,10,"$"
  34.  
  35. errmsg1         db      "Syntax: CMOSSAVE [d:][path]filename [/nnn]",13,10,"$"
  36. errmsg2         db      "The file already exists. Replace it (Y/N)? $"
  37. errmsg3         db      "Invalid path or file name. File could not be "
  38.                 db      "created.",13,10,"$"
  39. errmsg4         db      "Error writing file to disk",13,10,"$"
  40. errmsg5         db      "Disk full",13,10,"$"
  41. errmsg6         db      "Invalid numeric parameter or value out of range"
  42.                 db      13,10,"$"
  43.  
  44. msg             db      " bytes were copied from CMOS RAM to disk",13,10,"$"
  45.  
  46. handle          dw      ?                       ;File handle
  47. filename        dw      0                       ;Address of file name
  48. cmoslength      dw      ?                       ;Number of bytes to save
  49. nnn             dw      0                       ;Value of "nnn" parameter
  50.  
  51. ;****************************************************************************
  52. ; Procedure MAIN
  53. ;****************************************************************************
  54.  
  55. main            proc    near
  56.                 cld                             ;Clear direction flag
  57.                 mov     si,81h                  ;Point SI to command line
  58.                 call    scanhelp                ;Scan for "/?" switch
  59.                 jnc     main1                   ;Branch if not found
  60.  
  61.                 mov     ah,09h                  ;Display help text and exit
  62.                 mov     dx,offset helpmsg       ;with ERRORLEVEL=0
  63.                 int     21h
  64.                 mov     ax,4C00h
  65.                 int     21h
  66. ;
  67. ; Parse the command line.
  68. ;
  69. main1:          call    findchar                ;Find a parameter
  70.                 jc      main2                   ;Branch if end of line
  71.  
  72.                 cmp     byte ptr [si],"/"       ;Branch if the parameter
  73.                 je      main1a                  ;starts with a "/"
  74.  
  75.                 mov     filename,si             ;Save the address
  76.                 call    finddelim               ;Find the end of the string
  77.                 mov     byte ptr [si],0         ;Convert file name to ASCIIZ
  78.                 jc      main2                   ;Branch if end of line
  79.                 inc     si                      ;Advance SI
  80.                 jmp     main1                   ;Loop back for more
  81.  
  82. main1a:         inc     si                      ;Skip the "/" character
  83.                 call    asc2bin                 ;Read and convert the number
  84.                 mov     dx,offset errmsg6       ;Error if carry returns set
  85.                 jc      error
  86.                 cmp     ax,64                   ;Error if number is less
  87.                 jb      error                   ;than 64 or greater than
  88.                 cmp     ax,256                  ;256
  89.                 ja      error
  90.                 mov     nnn,ax                  ;Save the value
  91.                 jmp     main1                   ;Loop back for more
  92.  
  93. main2:          cmp     filename,0              ;Branch if a file name
  94.                 jne     main2a                  ;was entered
  95.  
  96.                 mov     dx,offset errmsg1       ;Point DX to error message
  97. error:          mov     ah,09h                  ;Display error message
  98.                 int     21h
  99. error_exit:     mov     ax,4C01h                ;Exit with ERRORLEVEL=1
  100.                 int     21h
  101.  
  102. main2a:         mov     cx,nnn                  ;Set CMOSLENGTH equal to
  103.                 mov     cmoslength,cx           ;NNN and branch if a number
  104.                 or      cx,cx                   ;was entered on the command
  105.                 jnz     main3                   ;line
  106.  
  107.                 call    getlength               ;Get CMOS length
  108.                 mov     cmoslength,cx           ;Save the result
  109. ;
  110. ; Create the data file.
  111. ;
  112. main3:          mov     ax,3D00h                ;Attempt to open the file
  113.                 mov     dx,filename             ;with DOS function 3Dh
  114.                 int     21h
  115.                 jc      main4                   ;Branch if the call failed
  116.  
  117.                 mov     bx,ax                   ;Close the file
  118.                 mov     ah,3Eh
  119.                 int     21h
  120.  
  121.                 mov     ah,09h                  ;Ask if user wants to
  122.                 mov     dx,offset errmsg2       ;overwrite it
  123.                 int     21h
  124.  
  125. ask:            mov     ah,08h                  ;Get the response
  126.                 int     21h
  127.                 or      al,al
  128.                 jnz     compare
  129.                 mov     ah,08h
  130.                 int     21h
  131.                 jmp     ask
  132.  
  133. compare:        cmp     al,"Y"                  ;Ask again if the answer
  134.                 je      yes                     ;isn't "Y" or "N"
  135.                 cmp     al,"y"
  136.                 je      yes
  137.                 cmp     al,"N"
  138.                 je      no
  139.                 cmp     al,"n"
  140.                 jne     ask
  141.  
  142. no:             mov     ah,02h                  ;Display "N" and abort
  143.                 mov     dl,"N"
  144.                 int     21h
  145.                 mov     ah,09h
  146.                 mov     dx,offset crlf
  147.                 int     21h
  148.                 jmp     error_exit
  149.  
  150. yes:            mov     ah,02h                  ;Display "Y" and continue
  151.                 mov     dl,"Y"
  152.                 int     21h
  153.                 mov     ah,09h
  154.                 mov     dx,offset crlf
  155.                 int     21h
  156.  
  157. main4:          mov     ah,3Ch                  ;Create the file by calling
  158.                 xor     cx,cx                   ;DOS function 3Ch
  159.                 mov     dx,filename
  160.                 int     21h
  161.                 mov     dx,offset errmsg3       ;Error if the file could
  162.                 jc      main6a                  ;not be created
  163.                 mov     handle,ax               ;Save the file handle
  164. ;
  165. ; Read the configuration data from CMOS RAM, compute the checksum, and
  166. ; write both to the file.
  167. ;
  168.                 mov     cx,8                    ;Copy the CMOSSAVE signature
  169.                 mov     si,offset copyright     ;to the output buffer
  170.                 mov     di,offset scanhelp
  171.                 rep     movsb
  172.  
  173.                 cld                             ;Clear direction flag
  174.                 xor     cx,cx                   ;Initialize counter
  175.  
  176. main5:          mov     al,cl                   ;Get address in AL
  177.                 cli                             ;Interrupts off
  178.                 out     CMOS_ADDR,al            ;Output CMOS address
  179.                 jmp     short $+2               ;I/O delay
  180.                 jmp     short $+2
  181.                 in      al,CMOS_DATA            ;Read one byte of CMOS data
  182.                 stosb                           ;Buffer the byte
  183.                 sti                             ;Interrupts on
  184.                 inc     cx                      ;Increment counter
  185.                 cmp     cx,cmoslength           ;Loop if there are more
  186.                 jne     main5                   ;bytes to save
  187.  
  188.                 xor     al,al                   ;Compute the checksum
  189.                 mov     cx,cmoslength
  190.                 add     cx,8
  191.                 mov     si,offset scanhelp
  192. main6:          add     al,[si]
  193.                 inc     si
  194.                 loop    main6
  195.                 stosb                           ;Copy checksum to buffer
  196.  
  197.                 mov     ah,40h                  ;Write the data to the file
  198.                 mov     bx,handle
  199.                 mov     cx,cmoslength
  200.                 add     cx,9
  201.                 mov     dx,offset scanhelp
  202.                 int     21h
  203.                 mov     dx,offset errmsg4
  204.                 jc      main6a                  ;Branch on error
  205.  
  206.                 cmp     ax,cx                   ;Error if the disk is
  207.                 je      main7                   ;full
  208.                 mov     dx,offset errmsg5
  209. main6a:         jmp     error
  210. ;
  211. ; Close the file, display message, and exit.
  212. ;
  213. main7:          mov     ah,3Eh                  ;Close the data file
  214.                 mov     bx,handle
  215.                 int     21h
  216.  
  217.                 mov     ah,09h                  ;Display copyright message
  218.                 mov     dx,offset copyright
  219.                 int     21h
  220.  
  221.                 mov     ax,cmoslength           ;Display the number of
  222.                 call    bin2asc                 ;bytes that were saved
  223.                 mov     ah,09h
  224.                 mov     dx,offset msg
  225.                 int     21h
  226.  
  227.                 mov     ax,4C00h                ;Exit with ERRORLEVEL=0
  228.                 int     21h
  229. main            endp
  230.  
  231. ;****************************************************************************
  232. ; GETLENGTH returns the number of bytes of CMOS RAM that this PC
  233. ; contains in CX. GETLENGTH will never return a value less than 64
  234. ; or greater than 256.
  235. ;****************************************************************************
  236.  
  237. getlength       proc    near
  238.                 mov     cx,64                   ;Initialize counter
  239.  
  240. gl_loop:        cli                             ;Interrupts off
  241.                 mov     al,cl                   ;Get address in AL
  242.                 out     CMOS_ADDR,al            ;Output CMOS address
  243.                 jmp     short $+2               ;I/O delay
  244.                 jmp     short $+2
  245.                 in      al,CMOS_DATA            ;Read one byte of CMOS data
  246.                 mov     bl,al                   ;Save the byte in BL
  247.                 sti                             ;Interrupts on
  248.  
  249.                 mov     al,0A5h                 ;Test this byte with
  250.                 call    testbyte                ;alternating 1s and 0s
  251.                 jc      gl_exit
  252.  
  253.                 mov     al,5Ah                  ;Test this byte with
  254.                 call    testbyte                ;alternating 0s and 1s
  255.                 jc      gl_exit
  256.  
  257.                 mov     al,00h                  ;Test this byte with
  258.                 call    testbyte                ;all 0s
  259.                 jc      gl_exit
  260.  
  261.                 mov     al,0FFh                 ;Test this byte with
  262.                 call    testbyte                ;all 1s
  263.                 jc      gl_exit
  264.  
  265.                 cli                             ;Interrupts off
  266.                 mov     al,cl                   ;Get address in AL
  267.                 out     CMOS_ADDR,al            ;Output CMOS address
  268.                 jmp     short $+2               ;I/O delay
  269.                 jmp     short $+2
  270.                 mov     al,bl                   ;Get original value in AL
  271.                 out     CMOS_DATA,al            ;Restore the byte
  272.                 sti                             ;Interrupts on
  273.  
  274.                 inc     cx                      ;Increment counter
  275.                 cmp     cx,256                  ;Loop back for more if
  276.                 jne     gl_loop                 ;CX is less than 256
  277.  
  278.                 mov     al,80h                  ;Make sure NMI is enabled
  279.                 out     CMOS_ADDR,al            ;if this happens to be a
  280.                 jmp     short $+2               ;PS/2
  281.                 jmp     short $+2
  282.                 in      al,CMOS_DATA
  283. gl_exit:        ret                             ;Return to caller
  284. getlength       endp
  285.  
  286. ;****************************************************************************
  287. ; TESTBYTE tests a byte of CMOS RAM to see if it really does contain RAM.
  288. ; On entry, CL holds the CMOS address. On return, carry is clear if the
  289. ; byte contains RAM, set if it does not.
  290. ;****************************************************************************
  291.  
  292. testbyte        proc    near
  293.                 mov     ah,al                   ;Save test value in AH
  294.  
  295.                 cli                             ;Interrupts off
  296.                 mov     al,cl                   ;Get address in AL
  297.                 out     CMOS_ADDR,al            ;Output CMOS address
  298.                 jmp     short $+2               ;I/O delay
  299.                 jmp     short $+2
  300.                 mov     al,ah                   ;Get test value in AL
  301.                 out     CMOS_DATA,al            ;Output the test value
  302.                 jmp     short $+2               ;I/O delay
  303.                 jmp     short $+2
  304.  
  305.                 mov     al,cl                   ;Get address in AL
  306.                 out     CMOS_ADDR,al            ;Output CMOS address
  307.                 jmp     short $+2               ;I/O delay
  308.                 jmp     short $+2
  309.                 in      al,CMOS_DATA            ;Read the test value back
  310.                 sti                             ;Interrupts on
  311.  
  312.                 cmp     al,ah                   ;Compare the values
  313.                 je      tb_exit                 ;Branch if they're equal
  314.  
  315.                 stc                             ;Set carry and return
  316.                 ret
  317.  
  318. tb_exit:        clc                             ;Clear carry and return
  319.                 ret
  320. testbyte        endp
  321.  
  322. ;****************************************************************************
  323. ; ASC2BIN converts the text pointed to by SI to a number and returns the
  324. ; value in AX. Carry returns set if the text contains an invalid character
  325. ; or if an overflow error occurred.
  326. ;****************************************************************************
  327.  
  328. asc2bin         proc    near
  329.                 cld                             ;Clear direction flag
  330.                 sub     ax,ax                   ;Initialize registers
  331.                 xor     bh,bh
  332.                 mov     cx,10
  333.  
  334. a2b_loop:       mov     bl,[si]                 ;Get a character
  335.                 inc     si
  336.                 cmp     bl,20h                  ;Exit if space
  337.                 je      a2b_exit
  338.                 cmp     bl,09h                  ;Exit if tab
  339.                 je      a2b_exit
  340.                 cmp     bl,2Ch                  ;Exit if comma
  341.                 je      a2b_exit
  342.                 cmp     bl,0Dh                  ;Exit if carriage return
  343.                 je      a2b_exit
  344.  
  345.                 cmp     bl,"0"                  ;Error if character is not
  346.                 jb      a2b_error               ;a number
  347.                 cmp     bl,"9"
  348.                 ja      a2b_error
  349.  
  350.                 mul     cx                      ;Multiply the value in AX
  351.                 jc      a2b_error               ;by 10 and exit on overflow
  352.                 sub     bl,30h                  ;ASCII => binary
  353.                 add     ax,bx                   ;Add latest value to AX
  354.                 jnc     a2b_loop                ;Loop back if no overflow
  355.  
  356. a2b_error:      dec     si                      ;Set carry and exit
  357.                 stc
  358.                 ret
  359.  
  360. a2b_exit:       dec     si                      ;Clear carry and exit
  361.                 clc
  362.                 ret
  363. asc2bin         endp
  364.  
  365. ;****************************************************************************
  366. ; BIN2ASC converts a binary value in AX to ASCII form and displays it.
  367. ;****************************************************************************
  368.  
  369. bin2asc         proc    near
  370.                 mov     bx,10                   ;Initialize divisor word and
  371.                 xor     cx,cx                   ;digit counter
  372. b2a1:           inc     cx                      ;Increment digit count
  373.                 xor     dx,dx                   ;Divide by 10
  374.                 div     bx
  375.                 push    dx                      ;Save remainder on stack
  376.                 or      ax,ax                   ;Loop until quotient is zero
  377.                 jnz     b2a1
  378. b2a2:           pop     dx                      ;Retrieve a digit from stack
  379.                 add     dl,30h                  ;Convert it to ASCII
  380.                 mov     ah,2                    ;Display it
  381.                 int     21h
  382.                 loop    b2a2                    ;Loop until done
  383.                 ret
  384. bin2asc         endp
  385.  
  386. ;****************************************************************************
  387. ; SCANHELP scans the command line for a /? switch. If found, carry returns
  388. ; set and SI contains its offset. If not found, carry returns clear.
  389. ;****************************************************************************
  390.  
  391. scanhelp        proc    near
  392.                 push    si                      ;Save SI
  393. scanloop:       lodsb                           ;Get a character
  394.                 cmp     al,0Dh                  ;Exit if end of line
  395.                 je      scan_exit
  396.                 cmp     al,"?"                  ;Loop if not "?"
  397.                 jne     scanloop
  398.                 cmp     byte ptr [si-2],"/"     ;Loop if not "/"
  399.                 jne     scanloop
  400.  
  401.                 add     sp,2                    ;Clear the stack
  402.                 sub     si,2                    ;Adjust SI
  403.                 stc                             ;Set carry and exit
  404.                 ret
  405.  
  406. scan_exit:      pop     si                      ;Restore SI
  407.                 clc                             ;Clear carry and exit
  408.                 ret
  409. scanhelp        endp
  410.  
  411. ;****************************************************************************
  412. ; FINDCHAR advances SI to the next non-white-space character. On return,
  413. ; carry set indicates EOL was encountered; carry clear indicates it was not.
  414. ;****************************************************************************
  415.  
  416. findchar        proc    near
  417.                 lodsb                           ;Get the next character
  418.                 cmp     al,09h                  ;Loop if tab
  419.                 je      findchar
  420.                 cmp     al,20h                  ;Loop if space
  421.                 je      findchar
  422.                 cmp     al,2Ch                  ;Loop if comma
  423.                 je      findchar
  424.                 dec     si                      ;Point SI to the character
  425.                 cmp     al,0Dh                  ;Exit with carry set if end
  426.                 je      eol                     ;of line is reached
  427.  
  428.                 clc                             ;Clear carry and exit
  429.                 ret
  430.  
  431. eol:            stc                             ;Set carry and exit
  432.                 ret
  433. findchar        endp
  434.  
  435. ;****************************************************************************
  436. ; FINDDELIM advances SI to the next white-space character. On return,
  437. ; carry set indicates EOL was encountered.
  438. ;****************************************************************************
  439.  
  440. finddelim       proc    near
  441.                 lodsb                           ;Get the next character
  442.                 cmp     al,09h                  ;Exit if tab
  443.                 je      fd_exit
  444.                 cmp     al,20h                  ;Exit if space
  445.                 je      fd_exit
  446.                 cmp     al,2Ch                  ;Exit if comma
  447.                 je      fd_exit
  448.                 cmp     al,0Dh                  ;Loop back for more if end
  449.                 jne     finddelim               ;of line isn't reached
  450.  
  451.                 dec     si                      ;Set carry and exit
  452.                 stc
  453.                 ret
  454.  
  455. fd_exit:        dec     si                      ;Clear carry and exit
  456.                 clc
  457.                 ret
  458. finddelim       endp
  459.  
  460. code            ends
  461.                 end     begin
  462.